~ chicken-core (chicken-5) /manual/Module (chicken foreign)
Trap1[[tags: manual]]2[[toc:]]34== Module (chicken foreign)56This module provides a ''foreign function interface'' to access externally7defined functions and variables in C-compatible languages, as well as8operating-system specific functionality.910Note that this interface is source-based, since CHICKEN translates11Scheme code to C. It is not binary, as in many other Scheme implementations.1213Several special forms of this interface refer to ''foreign type specifiers'',14consult the [[/manual/Foreign type specifiers|relevant chapter]] of this manual for15more information.161718== Accessing external objects1920=== foreign-code2122<macro>(foreign-code STRING ...)</macro>2324Executes the embedded C/C++ code {{STRING ...}}, which should25be a sequence of C statements, which are executed and return an unspecified result.2627<enscript highlight=scheme>28(foreign-code "doSomeInitStuff();") => #<unspecified>29</enscript>3031Code wrapped inside {{foreign-code}} may not invoke callbacks into Scheme.323334=== foreign-value3536<macro>(foreign-value CODE TYPE)</macro>3738Evaluates the embedded C/C++ expression {{CODE}} (which may be a string or symbol), returning a value of type given39in the foreign-type specifier {{TYPE}}.4041<enscript highlight=scheme>42(print (foreign-value "my_version_string" c-string))43</enscript>444546=== foreign-declare4748<macro>(foreign-declare STRING ...)</macro>4950Include given strings verbatim into header of generated file.515253=== define-foreign-type5455<macro>(define-foreign-type NAME TYPE [ARGCONVERT [RETCONVERT]])</macro>5657Defines an alias for {{TYPE}} with the name {{NAME}} (a symbol).58{{TYPE}} may be a type-specifier or a string naming a C type. The59namespace of foreign type specifiers is separate from the normal60Scheme namespace. The optional arguments {{ARGCONVERT}} and61{{RETCONVERT}} should evaluate to procedures that map argument- and62result-values to a value that can be transformed to {{TYPE}}:6364<enscript highlight=scheme>65(define-foreign-type char-vector66 nonnull-c-string67 (compose list->string vector->list)68 (compose list->vector string->list) )6970(define strlen71 (foreign-lambda int "strlen" char-vector) )7273(strlen '#(#\a #\b #\c)) ==> 37475(define memset76 (foreign-lambda char-vector "memset" char-vector char int) )7778(memset '#(#_ #_ #_) #\X 3) ==> #(#\X #\X #\X)79</enscript>8081Foreign type-definitions are only visible in the compilation-unit in which82they are defined, so use {{include}} to use the same definitions83in multiple files.848586=== foreign-type-size8788<macro>(foreign-type-size TYPE)</macro>8990Returns the size of the storage required to hold values of the91given foreign type {{TYPE}}. This is basically equivalent to9293<enscript highlight=scheme>94(foreign-value "sizeof(TYPE)" size_t)95</enscript>9697but also handles user-defined types and allows "TYPE" to be a string,98which will be given literally to the {{sizeof}} operator.99100101=== define-foreign-variable102103<macro>(define-foreign-variable NAME TYPE [STRING])</macro>104105Defines a foreign variable of name {{NAME}} (a symbol). {{STRING}}106should be the real name of a foreign variable or parameterless107macro. If {{STRING}} is not given, then the variable name {{NAME}}108will be converted to a string and used instead. All references and109assignments (via {{set!}}) are modified to correctly convert values110between Scheme and C representation. This foreign variable can only be111accessed in the current compilation unit, but the name can be112lexically shadowed. Note that {{STRING}} can name an arbitrary C113expression. If no assignments are performed, then {{STRING}} doesn't114even have to specify an lvalue.115See that {{define-foreign-variable}} will not generate C declarations116or memory allocation code; use it to include references to variables117in external C code. To actually create Scheme variables visible from C,118use {{define-external}} (see the Manual section on119[[/manual/Module (chicken foreign)#Callbacks|Callbacks]]).120For example, the following code:121<enscript lang="scheme">122(import (chicken foreign))123(define-foreign-variable x double "var_x")124(print x)125</enscript>126will not work, because a reference to {{var_x}} will be inserted in the C code,127but no declaration will be included (this can be easily verified by translating128the program into C with {{csc -t program.scm}}). Changing the second line to129{{(define-external x double 0.5)}} will work (and the value 0.5 will be printed).130131=== foreign-lambda132133<macro>(foreign-lambda RETURNTYPE NAME ARGTYPE ...)</macro>134135Represents a136binding to an external routine. This form can be used in the position137of an ordinary {{lambda}} expression. {{NAME}} specifies the138name of the external procedure and should be a string or a symbol.139140141=== foreign-lambda*142143<macro>(foreign-lambda* RETURNTYPE ((ARGTYPE VARIABLE) ...) STRING ...)</macro>144145Similar to {{foreign-lambda}}, but instead of generating code to146call an external function, the body of the C procedure is directly given147in {{STRING ...}}:148149<enscript highlight=scheme>150(define my-strlen151 (foreign-lambda* int ((c-string str))152 "int n = 0;153 while(*(str++)) ++n;154 C_return(n);") )155156(my-strlen "one two three") ==> 13157</enscript>158159For obscure technical reasons you should use the {{C_return}} macro instead of the normal {{return}} statement160to return a result from the foreign lambda body as some cleanup code has to be run before execution161commences in the calling code.162163=== foreign-safe-lambda164165<macro>(foreign-safe-lambda RETURNTYPE NAME ARGTYPE ...)</macro>166167This is similar to {{foreign-lambda}}, but also allows the called168function to call Scheme functions. See [[/manual/Module (chicken foreign)#Callbacks|Callbacks]].169170171=== foreign-safe-lambda*172173<macro>(foreign-safe-lambda* RETURNTYPE ((ARGTYPE VARIABLE)...) STRING ...)</macro>174175This is similar to {{foreign-lambda*}}, but also allows the called176function to call Scheme functions and allocate Scheme data-objects.177See [[/manual/Module (chicken foreign)#Callbacks|Callbacks]].178179180181=== foreign-primitive182183<macro>(foreign-primitive [RETURNTYPE] ((ARGTYPE VARIABLE) ...) STRING ...)</macro>184185This is also similar to {{foreign-lambda*}} but the code will be186executed in a ''primitive'' CPS context, which means it will not187actually return, but call its continuation on exit. This means that code188inside this form may allocate Scheme data on the C stack (the189''nursery'') with {{C_alloc}} (see below). You can return multiple190values inside the body of the {{foreign-primitive}} form by using191the following C code:192193<enscript highlight=scheme>194C_word av[N + 2] = { C_SCHEME_UNDEFINED, C_k, X1, ... };195C_values(N + 2, av);196</enscript>197198where {{N}} is the number of values to be returned, and {{X1, ...}}199are the results, which should be Scheme data objects.200See [[/manual/C interface#constructors|Constructors]] for the APIs to construct Scheme data objects from C primitives.201When returning multiple values, the return-type should be omitted.202Of course, if you have to dynamically compute the values, you do not have to use C's203array initialization syntax, but you can just assign them one by one.204205Returning just a single value can still be done via the {{C_return(...)}} macro.206207208== Callbacks209210211To enable an external C function to call back to Scheme, the form212{{foreign-safe-lambda}} (or {{foreign-safe-lambda*}})213has to be used. This generates special code to save and restore important214state information during execution of C code. There are two ways of215calling Scheme procedures from C: the first is to invoke the runtime216function {{C_callback}} with the closure to be called and the number217of arguments. The second is to define an externally visible wrapper218function around a Scheme procedure with the {{define-external}}219form.220221Note: the names of all functions, variables and macros exported by the222CHICKEN runtime system start with {{C_}}. It is advisable to223use a different naming scheme for your own code to avoid name clashes.224Callbacks (defined by {{define-external}})225do not capture the lexical environment.226227Non-local exits leaving the scope of the invocation of a callback from Scheme into C228will not remove the C call-frame from the stack (and will result in a memory229leak). '''Note:''' The same applies to230SRFI-18 threading, which is implemented with {{call/cc}};231additionally, if you enter one callback, switch threads and then exit232a different callback, your program is likely to crash.233234235=== define-external236237<macro>(define-external [QUALIFIERS] (NAME (ARGUMENTTYPE1 VARIABLE1) ...) RETURNTYPE BODY ...)</macro><br>238<macro>(define-external NAME TYPE [INIT])</macro>239240The first form defines an externally callable Scheme241procedure. {{NAME}} should be a symbol, which, when converted to a242string, represents a legal C identifier. {{ARGUMENTTYPE1 ...}} and243{{RETURNTYPE}} are foreign type specifiers for the argument variables244{{VAR1 ...}} and the result, respectively. {{QUALIFIERS}}245is an optional qualifier for the foreign procedure definition, like246{{__stdcall}}.247248<enscript highlight=scheme>249(define-external (foo (c-string x)) int (string-length x))250</enscript>251252You can use [[/manual/Module (chicken foreign)#location|{{location}}]]253to get a pointer to the defined C function, which can be passed to a254C function that takes a callback function pointer argument, for example.255256The second form of {{define-external}} can be used to define257variables that are accessible from foreign code. It declares258a global variable named by the symbol {{NAME}} that259has the type {{TYPE}}. {{INIT}} can be an arbitrary260expression that is used to initialize the variable. {{NAME}} is261accessible from Scheme just like any other foreign variable defined by262{{define-foreign-variable}}.263264<enscript highlight=scheme>265(define-external foo int 42)266((foreign-lambda* int ()267 "C_return(foo);")) ==> 42268</enscript>269270'''Note:''' don't be tempted to271assign strings or bytevectors to external variables. Garbage collection272moves those objects around, so it is a very bad idea to assign pointers273to heap-data. If you have to do so, then copy the data object into274statically allocated memory (for example by using {{object-evict}}).275276Results of type {{scheme-object}} returned by {{define-external}}277are always allocated in the secondary heap, that is, not in the stack.278279=== C_callback280281 [C function] C_word C_callback (C_word closure, int argc)282283This function can be used to invoke the Scheme procedure {{closure}}.284{{argc}} should contain the number of arguments that are passed to285the procedure on the temporary stack. Values are put onto the temporary286stack with the {{C_save}} macro.287288=== C_callback_adjust_stack289290 [C function] void C_callback_adjust_stack (C_word *ptr, int size)291292The runtime-system uses the stack as a special allocation area and293internally holds pointers to estimated limits to distinguish between294Scheme data objects inside the stack from objects outside of it. If295you invoke callbacks at wildly differing stack-levels, these limits296may shift from invocation to invocation. Callbacks defined with297{{define-external}} will perform appropriate adjustments298automatically, but if you invoke {{C_callback}} manually, you should299perform a {{C_callback_adjust_stack}} to make sure the internal limits300are set properly. {{ptr}} should point to some data object on the301stack and {{size}} is the number of words contained in the data object302(or some estimate). The call will make sure the limits are adjusted so303that the value pointed to by {{ptr}} is located in the stack.304305== Locations306307It is also possible to define variables containing unboxed C data,308so called ''locations''. It should be noted that locations may309only contain simple data, that is: everything that fits into a310machine word, and double-precision floating point values.311312313314=== define-location315316<macro>(define-location NAME TYPE [INIT])</macro>317318Identical to {{(define-external NAME TYPE [INIT])}}, but the variable319is not accessible from outside of the current compilation unit (it is320declared {{static}}).321322=== let-location323324<macro>(let-location ((NAME TYPE [INIT]) ...) BODY ...)</macro>325326Defines a lexically bound location.327328=== location329330<macro>(location NAME)</macro><br>331<macro>(location X)</macro>332<read>#$</read>333334This form returns a pointer object335that contains the address of the variable {{NAME}}.336If the argument to {{location}} is not a location defined by {{define-location}},337{{define-external}} or {{let-location}}, then338339 (location X)340341is essentially equivalent to342343 (make-locative X)344345(See the [[/manual/Module (chicken locative)|manual section on locatives]] for more346information about locatives)347348Note that {{(location X)}} may be abbreviated as {{#$X}}.349350<enscript highlight=scheme>351(define-external foo int)352((foreign-lambda* void (((c-pointer int) ip)) "*ip = 123;")353 (location foo))354foo ==> 123355</enscript>356357This facility is especially useful in situations, where a C function358returns more than one result value:359360<enscript highlight=scheme>361#>362#include <math.h>363<#364365(define modf366 (foreign-lambda double "modf" double (c-pointer double)) )367368(let-location ([i double])369 (let ([f (modf 1.99 (location i))])370 (print "i=" i ", f=" f) ) )371</enscript>372373See [[/location-and-c-string-star|location and c-string*]]374for a tip on returning a {{c-string*}} type.375376{{location}} returns a value of type {{c-pointer}}, when given377the name of a callback-procedure defined with {{define-external}}.378379---380Previous: [[Module (chicken flonum)]]381382Next: [[Module (chicken format)]]